<?php

namespace Drupal\timer_call\Entity;

use Drupal\gateway_client\GatewayClient;
use Drupal\timer_call\Interfaces\TimerCallRunInterface;
use Entity;
use Exception;

class TimerCall extends Entity {

  public $id;

  public $time = 0;

  public $event;

  public $value;

  public $token;

  public $uid;

  public $status = 0;

  public $created;

  public $changed;

  protected $push;

  function __construct($values = []) {
    $this->push = new GatewayClient();
    parent::__construct($values, 'timer_call');
  }

  static function initByController(TimerCallRunInterface $callRun) {
    $event = $callRun->getEvent();
    $es = entity_load('timer_call', FALSE, ['event' => $event]);
    if (!empty($es)) {
      $e = reset($es);
    }
    else {
      $e = new static();
    }
    $e->setController($callRun);
    return $e;
  }

  function setController(TimerCallRunInterface $callRun) {
    $this->time = $callRun->getTime();
    $this->event = $callRun->getEvent();
    $this->value = serialize($callRun);
    return $this;
  }

  function doRun() {
    if ($this->status == 0) {
      $db_transaction = db_transaction();
      try {
        $class = unserialize($this->value);
        if ($class instanceof TimerCallRunInterface) {
          $class->run();
          $this->status = 1;
          $this->save();
          return TRUE;
        }
        throw new Exception('接口实现错误');
      } catch (Exception $exception) {
        $db_transaction->rollback();
        watchdog_exception(__FUNCTION__, $exception);
      }
    }
  }

  public function save() {
    $this->changed = REQUEST_TIME;
    if (empty($this->created)) {
      $this->created = REQUEST_TIME;
    }
    if (empty($this->token)) {
      $this->token = REQUEST_TIME . drupal_random_key(64);
    }
    if (empty($this->uid)) {
      global $user;
      $this->uid = $user->uid;
    }
    parent::save();

    if ($this->status == 0) {
      $callback = "/timer-call/{$this->id}/{$this->token}";
      $event = 'timer_call_' . $this->id;
      $this->push->pushTimer($this->time, $event, $callback);
    }
  }
}
